import { Node, Prefab, UITransform, Vec3, instantiate } from 'cc'
import { GridRandomPositions } from './GridRandomPositions'

/** 布局项信息接口 */
interface LayoutItemInfo {
	/** 节点对象 */
	node: Node
	/** Y轴坐标值,用于深度排序 */
	yPos: number
}

/** 网格布局配置接口 */
interface GridLayoutConfig {
	cellWidth: number
	cellHeight: number
}

/**
 * 网格布局随机分布工具类
 * 用于在容器中随机分布预制体实例,并按Y轴坐标排序
 */
export class GridLayoutUtil {
	/** 容器节点 */
	private container: Node
	/** 预制体对象 */
	private itemPrefab: Prefab
	/** 布局项数量 */
	private itemCount: number
	/** 布局配置 */
	private config: GridLayoutConfig
	/** 节点列表 */
	private nodeList: Node[] = []

	/**
	 * 构造函数
	 * @param container 容器节点
	 * @param itemPrefab 预制体对象
	 * @param itemCount 布局项数量
	 * @param config 布局配置
	 */
	constructor(container: Node, itemPrefab: Prefab, itemCount: number, config: GridLayoutConfig) {
		this.container = container
		this.itemPrefab = itemPrefab
		this.itemCount = itemCount
		this.config = config
	}

	/**
	 * 创建网格布局
	 * @returns 布局节点列表
	 */
	public createLayout(): Node[] {
		this.clearContainer()
		const positions = this.generateGridPositions()
		const items = this.createLayoutItems(positions)
		this.sortItemsByDepth(items)
		return this.nodeList
	}
	/**
	 * 更新布局项数量并重新生成布局
	 * @param newCount 新的布局项数量
	 * @returns 更新后的布局节点列表
	 */
	public updateItemCount(newCount: number) {
		this.itemCount = newCount
	}

	/** 清空容器内所有节点和节点列表 */
	private clearContainer(): void {
		this.container.removeAllChildren()
		this.nodeList = []
	}

	/**
	 * 生成网格随机位置
	 * @returns 位置坐标数组
	 */
	private generateGridPositions(): Vec3[] {
		const transform = this.container.getComponent(UITransform)
		const grid = new GridRandomPositions(
			transform.width,
			transform.height,
			this.config.cellWidth,
			this.config.cellHeight
		)
		return grid.getRandomPositions(this.itemCount)
	}

	/**
	 * 创建布局项节点
	 * @param positions 位置坐标数组
	 * @returns 布局项信息数组
	 */
	private createLayoutItems(positions: Vec3[]): LayoutItemInfo[] {
		return positions.map(pos => {
			const itemNode = instantiate(this.itemPrefab)
			itemNode.setParent(this.container)
			itemNode.setPosition(pos)

			this.nodeList.push(itemNode)

			return { node: itemNode, yPos: pos.y }
		})
	}

	/**
	 * 根据Y轴坐标对布局项进行深度排序
	 * Y值越大显示层级越低
	 * @param items 布局项信息数组
	 */
	private sortItemsByDepth(items: LayoutItemInfo[]): void {
		items.sort((a, b) => b.yPos - a.yPos).forEach((item, index) => item.node.setSiblingIndex(index))
	}
}
